import com.jcraft.jsch.Channel
import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.SftpException
import net.sshiffon.*
import com.jcraft.jsch.ChannelSftp.LsEntry

class RemoteFileViewerController {
    // these will be injected by Griffon
    def model
    def view

    Channel channel

    ChannelSftp chSftp
    boolean isConnected=false

    void mvcGroupInit(Map<String,Object> args) {
    }

    boolean start()
	{
    	refresh()
    	return true
	}

    
    void quit()
    {
		view.fileList.metaClass.removeProppertyChangeListener= { 
    			String n, c ->
    			logger.debug('covering Groovy1.6 bug')
    			view.fileList.removePropertyChangeListener(n, c)
    		}
		destroyMVCGroup(model.mvcId);

    }

    void upload(String file)
    {
        initChannel()
        logger.info("Uploading ${file}")

        view.doOutside {
            try {
                chSftp.put(file,model.currentFolder, new SftpProgress())
                doLater {
                    refresh()
                }
            } catch (e)
            {
                logger.error("error uploading file ${file}",e)
            }
        }
    }

    void initChannel()
    {
        if(isConnected==false)
        {
            def session = model.parentController.model.session
            channel = session.openChannel("sftp")
            channel.connect();
            chSftp=(ChannelSftp)channel;
            isConnected=true
            model.currentFolder = chSftp.pwd()
        }
    }


    void mkdir(String name)
    {
        view.doOutside {
            try {
                chSftp.mkdir(name)
                doLater {
                    refresh()
                }
            } catch (e)
            {
                logger.error("Error making folder ${name}",e)
            }
        }
    }

    def upDir = {
            if(model.currentFolder.lastIndexOf('/')>-1)
            {
                    def file = model.currentFolder.substring(0,model.currentFolder.lastIndexOf('/')) + '/'
                    logger.debug("cding up to $file")
                    cd(file)
            } else {
            	logger.warn("nowhere up to go")
            }
    }

    void cd(String file)
    {

        logger.info("changing directory to ${file}")
        view.doOutside {
            try {
                chSftp.cd(file)
                model.currentFolder = chSftp.pwd()
                doLater {
                    refresh()
                }
                
            } catch (e)
            {
                logger.error("Error changing folder to ${file}",e)
            }
        }
    }
    
    void processEntry(entry)
    {
        def type = entry.type
        LsEntry lsEntry = entry.entry
        if(type=='D')
        {
            if('..'.equals(entry.name))
            {
            	upDir()
            } else {
                cd(model.currentFolder + '/' + entry.name)
            }

        } else {
            download(entry.name)
            model.parentController.model.localGroup.controller.refresh()
        }
    }

    void download(int modelRef)
    {
        def entry= model.folderContents[modelRef]
        if('D'.equals(entry.type))
        {
        	recurseDownload(entry.name)
        	//refresh()
        } else {
        	download(entry.name)
        }
        
    }

    void recurseDownload(String dirname)
    {
    	logger.debug("local mkdir ${dirname}")
    	model.parentController.model.localGroup.controller.mkdir(dirname)
    	logger.debug("local cdRelative ${dirname}")
    	def localFolder= model.parentController.model.localGroup.controller.getAbsoluteDirFromRelative(dirname)
    	
    	//>ls remote (and local?)
    	//logger.debug("channel localcd ${localFolder}")
    	//chSftp.lcd(localFolder)
    	//refresh()

    	logger.debug("sftp ls ${dirname}")
    	java.util.Vector vv = chSftp.ls(dirname)
    	//model.currentFolder+='/'+dirname
    	chSftp.cd(dirname);
        if(vv!=null){
          for(int ii=0; ii<vv.size(); ii++)
          {
            Object obj=vv.elementAt(ii);
            if(obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry)
            {
                com.jcraft.jsch.ChannelSftp.LsEntry entry = ((com.jcraft.jsch.ChannelSftp.LsEntry)obj)
                if(entry.getFilename()!='.' && entry.getFilename()!='..')
                {
                    //entry.getAttrs()
                    
                    if(entry.getAttrs().isDir())
                    {
                    	logger.debug(">>recurse into folder ${entry.filename} (ignoring for now)")
                    	//recurse here
                    } else {
                    	def pwd= chSftp.pwd()
                    	logger.debug(">>get file ${entry.filename} from ${pwd}")
                        downloadNoRefresh(entry.getFilename(), localFolder)
                    }
                }
            }
          }
        }
    	//>check file/folder types in each
    	//>recurse each (non-..) folder
    	//>download each file
    }

    void downloadNoRefresh(String file, String dest)
    {
        try {
        	chSftp.get(file,dest,new SftpProgress())
        } catch (e)
        {
            logger.error("Error downloading ${file}",e)
        }
    }

    void download(String file)
    {
        initChannel()
        logger.info("Downloading ${file}")
        def dest = model.parentController.model.localGroup.model.currentFolder
        view.doOutside {
            try {
                chSftp.get(file,dest,new SftpProgress())
				doLater {
                	model.parentController.model.localGroup.controller.refresh()
                }
            } catch (e)
            {
                logger.error("Error downloading ${file}",e)
            }
        }
    }
    void delete(int modelRef)
    {
        def entry= model.folderContents[modelRef]
        delete(entry.name)
    }

    void delete(String file)
    {
    	view.doOutside {
    		try {
    	    	chSftp.rm(file)
                doLater {
                    refresh()
                }
    		} catch(e)
    		{
 			   logger.error("Error deleting ${file}",e)
    		}
    		
    	}
    }

    void refreshModel()
    {
        initChannel()


      try{
        	java.util.Vector vv=chSftp.ls(model.currentFolder);
            model.loadContents(vv)
	  }
	  catch(SftpException e){
	    logger.error("Sftp Error whilst calling 'ls'", e)
            cd(chSftp.getHome())
	  }
    }

    void refresh()
    {
    	view.doOutside {
    		refreshModel()
    		doLater {
    			view.loadFolderAction.closure(model.currentFolder,model.folderContents)
    		}
    	}
    }
}